package com.ruoyi.exitwarehouse.controller;

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.text.ParseException;
import com.ruoyi.common.enums.RuleType;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.order.OrderUtils;
import com.ruoyi.enterwarehouse.domain.WEnterWarehouseInfo;
import com.ruoyi.fee.domain.WGoodsTransferFeeRule;
import com.ruoyi.fee.domain.WOverdueFeeRule;
import com.ruoyi.fee.domain.WWarehouseFeeRule;
import com.ruoyi.fee.service.IWOverdueFeeRuleService;
import com.ruoyi.fee.service.IWWarehouseFeeRuleService;
import com.ruoyi.goods.domain.TGoodsInfo;
import com.ruoyi.goods.domain.TGoodsWeightSum;
import com.ruoyi.goods.domain.WGoodsExt;
import com.ruoyi.goods.domain.WGoodsExtAssist;
import com.ruoyi.goods.service.ITGoodsInfoService;
import com.ruoyi.goods.service.IWGoodsExtAssistService;
import com.ruoyi.goods.service.IWGoodsExtService;
import com.ruoyi.system.domain.TVehicleDriverInfo;
import com.ruoyi.system.service.ITVehicleDriverInfoService;
import com.ruoyi.transfers.domain.WGoodsTransferAccount;
import com.ruoyi.transfers.domain.WGoodsTransferInfo;
import com.ruoyi.warehouse.domain.WWarehouseFeeAccount;
import com.ruoyi.warehouse.service.IWWarehouseFeeAccountService;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.exitwarehouse.domain.WExitWarehouseInfo;
import com.ruoyi.exitwarehouse.service.IWExitWarehouseInfoService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 出库信息Controller
 * 
 * @author wzy
 * @date 2024-05-25 18:52:54
 */
@RestController
@RequestMapping("/exitwarehouse/exit")
public class WExitWarehouseInfoController extends BaseController
{
    @Autowired
    private IWExitWarehouseInfoService wExitWarehouseInfoService;

    @Autowired
    private ITGoodsInfoService tGoodsInfoService;

    @Autowired
    private IWWarehouseFeeRuleService wWarehouseFeeRuleService;

    @Autowired
    private IWOverdueFeeRuleService wOverdueFeeRuleService;

    @Autowired
    private IWWarehouseFeeAccountService wWarehouseFeeAccountService;

    @Autowired
    private ITVehicleDriverInfoService tVehicleDriverInfoService;

    @Autowired
    private IWGoodsExtService wGoodsExtService;

    @Autowired
    private IWGoodsExtAssistService wGoodsExtAssistService;

    private static Logger logger = LoggerFactory.getLogger(WExitWarehouseInfoController.class);
    /**
     * 查询出库信息列表
     */
    @PreAuthorize("@ss.hasAnyPermi('exitwarehouse:exit:list, exitwarehouse:pick:list, exitwarehouse:plan:list, exitwarehouse:task:list, exitwarehouse:receipt:list')")
    @GetMapping("/list")
    public TableDataInfo list(WExitWarehouseInfo wExitWarehouseInfo)
    {
        startPage();
        List<WExitWarehouseInfo> list = wExitWarehouseInfoService.selectWExitWarehouseInfoList(wExitWarehouseInfo);
        return getDataTable(list);
    }

    /**
     * 导出出库信息列表
     */
    @PreAuthorize("@ss.hasAnyPermi('exitwarehouse:exit:export, exitwarehouse:pick:export, exitwarehouse:plan:export, exitwarehouse:task:export, exitwarehouse:receipt:export')")
    @Log(title = "出库信息", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, WExitWarehouseInfo wExitWarehouseInfo)
    {
        List<WExitWarehouseInfo> list = wExitWarehouseInfoService.selectWExitWarehouseInfoList(wExitWarehouseInfo);
        ExcelUtil<WExitWarehouseInfo> util = new ExcelUtil<WExitWarehouseInfo>(WExitWarehouseInfo.class);
        util.exportExcel(response, list, "出库信息数据");
    }

    /**
     * 获取出库信息详细信息
     */
    @PreAuthorize("@ss.hasAnyPermi('exitwarehouse:exit:query, exitwarehouse:pick:query, exitwarehouse:plan:query, exitwarehouse:task:query, exitwarehouse:receipt:query')")
    @GetMapping(value = "/{exitWarehouseId}")
    public AjaxResult getInfo(@PathVariable("exitWarehouseId") Long exitWarehouseId)
    {
        return success(wExitWarehouseInfoService.selectWExitWarehouseInfoByExitWarehouseId(exitWarehouseId));
    }

    /**
     * 新增出库信息
     */
    @PreAuthorize("@ss.hasAnyPermi('exitwarehouse:exit:add, exitwarehouse:pick:add, exitwarehouse:plan:add, exitwarehouse:task:add, exitwarehouse:receipt:add')")
    @Log(title = "出库信息", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody WExitWarehouseInfo wExitWarehouseInfo)
    {
        wExitWarehouseInfo.setExitWarehouseNumber(OrderUtils.getOrderNumber("EX", "-"));
        wExitWarehouseInfo.setCreateBy(getNickName());
        updateMobileAndNumberRelateInfo(wExitWarehouseInfo);
        wExitWarehouseInfo.setNumberOfPiece(handleMineTGoodsInfo(BusinessType.INSERT, wExitWarehouseInfo));
        return toAjax(wExitWarehouseInfoService.insertWExitWarehouseInfo(wExitWarehouseInfo));
    }

    /**
     * 修改出库信息
     */
    @PreAuthorize("@ss.hasAnyPermi('exitwarehouse:exit:edit, exitwarehouse:pick:edit, exitwarehouse:plan:edit, exitwarehouse:task:edit, exitwarehouse:receipt:edit')")
    @Log(title = "出库信息", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody WExitWarehouseInfo wExitWarehouseInfo)
    {
        wExitWarehouseInfo.setUpdateBy(getNickName());
        wExitWarehouseInfo.setNumberOfPiece(handleMineTGoodsInfo(BusinessType.UPDATE, wExitWarehouseInfo));
        return toAjax(wExitWarehouseInfoService.updateWExitWarehouseInfo(wExitWarehouseInfo));
    }

    /**
     * 删除出库信息
     */
    @PreAuthorize("@ss.hasAnyPermi('exitwarehouse:exit:remove, exitwarehouse:pick:remove, exitwarehouse:plan:remove, exitwarehouse:task:remove, exitwarehouse:receipt:remove')")
    @Log(title = "出库信息", businessType = BusinessType.DELETE)
	@DeleteMapping("/{exitWarehouseIds}")
    public AjaxResult remove(@PathVariable Long[] exitWarehouseIds)
    {
        /* 清除货物信息中，出库相关信息 */
        WExitWarehouseInfo exitWarehouseInfo = new WExitWarehouseInfo();
//        tGoodsInfoService.updateTGoodsInfoRelExitWarehouseFieldsByExitWarehouseIds(exitWarehouseIds, exitWarehouseInfo, "已在库");
        tGoodsInfoService.deleteTGoodsInfoByOtherIdsExt(1, exitWarehouseIds);
        return toAjax(wExitWarehouseInfoService.deleteWExitWarehouseInfoByExitWarehouseIds(exitWarehouseIds));
    }

    /**
     * 修改出库信息，创建出库计划
     */
    //@PreAuthorize("@ss.hasPermi('exitwarehouse:exit:edit')")
    @Log(title = "出库信息", businessType = BusinessType.UPDATE)
    @PutMapping("/createplan")
    public AjaxResult createplan(@RequestBody WExitWarehouseInfo wExitWarehouseInfo)
    {
        wExitWarehouseInfo.setUpdateBy(getNickName());
        return toAjax(wExitWarehouseInfoService.updateWExitWarehouseInfo(wExitWarehouseInfo));
    }

    /**
     * 修改出库单状态，确认出库
     */
    //@PreAuthorize("@ss.hasPermi('enterwarehouse:enter:edit')")
    @Log(title = "确认出库", businessType = BusinessType.CONFIRM)
    @PutMapping("/confirm")
    public AjaxResult confirm(@RequestBody WExitWarehouseInfo wExitWarehouseInfo)
    {
        Integer rtn = 0;
//        logger.debug("WWW " + "wExitWarehouseInfo = " + wExitWarehouseInfo);
        wExitWarehouseInfo.setUpdateBy(getNickName());
        wExitWarehouseInfo.setExitWarehouseConfirmPerson(getNickName());
        wExitWarehouseInfo.setExitWarehouseConfirmTime(DateUtils.getNowDate());
        wExitWarehouseInfo.setJobStatus("3");
        tGoodsInfoService.updateTGoodsConfirmRelFieldsByExitWarehouseNumber(wExitWarehouseInfo, "已出库");
        /**
         * 处理煤炭库存，计算出库账单
         */
        if(wExitWarehouseInfo.getGoodsType().equals("煤炭"))
        {
            handleMineInventory(BusinessType.CONFIRM, wExitWarehouseInfo);
            handleMineWarehouseFeeAccount(wExitWarehouseInfo);
        } else {
            handleWarehouseFeeAccount(wExitWarehouseInfo);
        }
        rtn = wExitWarehouseInfoService.updateWExitWarehouseInfo(wExitWarehouseInfo);
        return toAjax(rtn);
    }

    /**
     * 修改出库单状态，撤销出库
     */
    //@PreAuthorize("@ss.hasPermi('enterwarehouse:enter:edit')")
    @Log(title = "撤销出库", businessType = BusinessType.REVOKE)
    @PutMapping("/revoke")
    public AjaxResult revoke(@RequestBody WExitWarehouseInfo wExitWarehouseInfo)
    {
        Integer rtn = 0;
//        logger.debug("WWW " + "wExitWarehouseInfo = " + wExitWarehouseInfo);
        wExitWarehouseInfo.setUpdateBy(getNickName());
        wExitWarehouseInfo.setCreateBy(null);
        wExitWarehouseInfo.setExitWarehouseTime(null);
        wExitWarehouseInfo.setExitWarehouseConfirmPerson(null);
        wExitWarehouseInfo.setExitWarehouseConfirmTime(null);
        wExitWarehouseInfo.setJobStatus("2");
        rtn = tGoodsInfoService.updateTGoodsConfirmRelFieldsByExitWarehouseNumber(wExitWarehouseInfo, "出库中");

        /**
         * 处理煤炭库存，计算出库账单
         */
        if(wExitWarehouseInfo.getGoodsType().equals("煤炭"))
        {
            handleMineInventory(BusinessType.REVOKE, wExitWarehouseInfo);
        }

        //删除账单
        rtn = wWarehouseFeeAccountService.deleteWWarehouseFeeAccountByWarehouseFeeAccountNumber(wExitWarehouseInfo.getExitWarehouseNumber().replace("EX","WA"));

        rtn = wExitWarehouseInfoService.updateWExitWarehouseInfo(wExitWarehouseInfo);
        return toAjax(rtn);
    }

    /**
     *处理仓储费账单
     */
    private Integer handleWarehouseFeeAccount(WExitWarehouseInfo wExitWarehouseInfo)
    {
        Integer rtn = 0;

        List<TGoodsInfo> list = tGoodsInfoService.selectTGoodsInfoByNumber(3, wExitWarehouseInfo.getExitWarehouseNumber());

        String goodsType = wExitWarehouseInfo.getGoodsType();
        Double indoorWarehousePrice = 0.0;
        Double outdoorWarehousePrice = 0.0;
        Double warehouseWeight = 0.0;
        Double warehouseFee = 0.0;
        Double goodsWarehouseFee = 0.0;
        Double goodsWeight = 0.0;

        WWarehouseFeeAccount warehouseFeeAccount = new WWarehouseFeeAccount();
        warehouseFeeAccount.setWarehouseFeeAccountNumber(wExitWarehouseInfo.getExitWarehouseNumber().replace("EX","WA"));
        //仓储费列表
        List<WWarehouseFeeRule> warehouseFeelist = wWarehouseFeeRuleService.selectWWarehouseFeeRuleListByCustomerName(wExitWarehouseInfo.getExitWarehouseCustomer());
//        logger.debug("WWW " + "warehouseFeelist = " + warehouseFeelist);
        if(warehouseFeelist.size() > 0) {
            for (WWarehouseFeeRule item : warehouseFeelist) {
                if (item.getRuleType().equals(RuleType.COMMON.getInfo()) & item.getGoodsType().equals(goodsType)) {
                    indoorWarehousePrice = item.getIndoorWarehousePrice();
                    outdoorWarehousePrice = item.getOutdoorWarehousePrice();
                }
                if (item.getRuleType().equals(RuleType.CUSTOMIZED.getInfo()) & item.getGoodsType().equals(goodsType)) {
                    indoorWarehousePrice = item.getIndoorWarehousePrice();
                    outdoorWarehousePrice = item.getOutdoorWarehousePrice();
                }
            }

            for (TGoodsInfo item : list) {
                goodsWeight = item.getWeight();
                warehouseWeight = warehouseWeight + goodsWeight;
                item.setIndoorWarehousePrice(indoorWarehousePrice);
                item.setOutdoorWarehousePrice(outdoorWarehousePrice);
//                logger.debug("handleWarehouseFeeAccount ... item.getWarehouseType() = {}", item.getWarehouseType());
                if ((!(item.getWarehouseType() == null || item.getWarehouseType().isEmpty())) && item.getWarehouseType().equals("室外库")) {
                    goodsWarehouseFee = Math.round(outdoorWarehousePrice * goodsWeight * 100.0) / 100.0;
                } else {
                    goodsWarehouseFee = Math.round(indoorWarehousePrice * goodsWeight * 100.0) / 100.0;
                }
                item.setStorageFee(goodsWarehouseFee);
                warehouseFee = warehouseFee + goodsWarehouseFee;
            }
            warehouseFeeAccount.setIndoorWarehousePrice(indoorWarehousePrice);
            warehouseFeeAccount.setOutdoorWarehousePrice(outdoorWarehousePrice);
            warehouseFee = Math.round(warehouseFee * 100.0) / 100.0;
            warehouseFeeAccount.setStorageFee(warehouseFee);
        } else {
            logger.error("No Warehouse Fee Rule ...");
        }

        Integer freeStorageDays = 0;
        String overduePriceMode = "";
        Double overduePrice = 0.0;
        Double overdueGoodsFee = 0.0;
        Double overdueWarehouseFee = 0.0;
        Integer betweenDays = 0;

        // 超期费列表
        List<WOverdueFeeRule> overdueFeelist = wOverdueFeeRuleService.selectWOverdueFeeRuleListByCustomerName(wExitWarehouseInfo.getExitWarehouseCustomer());
//        logger.debug("WWW " + "overdueFeelist = " + overdueFeelist);
        if(overdueFeelist.size() > 0) {
            for (WOverdueFeeRule item : overdueFeelist) {
                if (item.getRuleType().equals(RuleType.COMMON.getInfo()) & item.getGoodsType().equals(goodsType)) {
                    freeStorageDays = item.getFreeStorage();
                    overduePriceMode = item.getOverduePriceMode();
                    overduePrice = item.getOverduePrice();
                }
                if (item.getRuleType().equals(RuleType.CUSTOMIZED.getInfo()) & item.getGoodsType().equals(goodsType)) {
                    freeStorageDays = item.getFreeStorage();
                    overduePriceMode = item.getOverduePriceMode();
                    overduePrice = item.getOverduePrice();
                }
            }
            //从入库单据，货物，入手
            for (TGoodsInfo item : list) {
                item.setFreeStorage(freeStorageDays);
                item.setOverduePriceMode(overduePriceMode);
                item.setOverduePrice(overduePrice);
                if( (item.getExitWarehouseTime() == null) || (item.getEnterWarehouseTime() == null)) {
                    betweenDays = 0;
                    logger.error("ExitWarehouseTime or EnterWarehouseTime is null, betweenDays = 0");
                } else {
                    betweenDays = Math.toIntExact((item.getExitWarehouseTime().getTime() - item.getEnterWarehouseTime().getTime())/(24 * 60 * 60 *1000));
                }
//            logger.debug("WWW " + "betweenDays  = " + betweenDays);
//            logger.debug("WWW " + "freeStorageDays  = " + freeStorageDays);

                if (overduePriceMode.equals("吨x天")) {
                    if (betweenDays > freeStorageDays) {
                        overdueGoodsFee = overduePrice * (betweenDays - freeStorageDays) * item.getWeight();
                        overdueGoodsFee = Math.round(overdueGoodsFee * 100.0) / 100.0;
                        item.setOverdueFee(overdueGoodsFee);
                        overdueWarehouseFee = overdueWarehouseFee + overdueGoodsFee;
                    } else {
                        item.setOverdueFee(0.0);
                    }
                } else if (overduePriceMode.equals("吨x月")) {
                    // 每月按30天计算
                    if ((betweenDays - freeStorageDays) < 30) {
                        item.setOverdueFee(0.0);
                    } else {
                        overdueGoodsFee = overduePrice * (betweenDays - freeStorageDays) * item.getWeight() / 30.0;
                        overdueGoodsFee = Math.round(overdueGoodsFee * 100.0) / 100.0;
                        item.setOverdueFee(overdueGoodsFee);
                        overdueWarehouseFee = overdueWarehouseFee + overdueGoodsFee;
                    }
                }
            }
            //超期费，免堆天数
            warehouseFeeAccount.setFreeStorage(freeStorageDays);
            //超期费，计算模式
            warehouseFeeAccount.setOverduePriceMode(overduePriceMode);
            //超期费，单价
            warehouseFeeAccount.setOverduePrice(overduePrice);
            //超期费，总数
            warehouseFeeAccount.setOverdueFee(overdueGoodsFee);
            //账单，结算模式
            warehouseFeeAccount.setWarehouseSettlementMode(wExitWarehouseInfo.getSettlementMode());
            warehouseFeeAccount.setCreateBy(getNickName());
            warehouseFeeAccount.setCreateTime(DateUtils.getNowDate());
            //仓储费合计
            warehouseFeeAccount.setWarehouseFeeTotal(Math.round(((warehouseFee + overdueWarehouseFee) * 100.0)) / 100.0);
//        warehouseFeeAccount.setWarehouseFeeTotal(warehouseFee + overdueWarehouseFee);

            warehouseFeeAccount.setWarehouseSettlementCustomer(wExitWarehouseInfo.getExitWarehouseCustomer());
            warehouseFeeAccount.setWarehouseSettlementMode(wExitWarehouseInfo.getSettlementMode());
            warehouseFeeAccount.setWarehouseSettlementMode(wExitWarehouseInfo.getSettlementMode());
        } else {
            logger.error("No Overdue Fee Rule ...");
        }
        //删除账单
        rtn = wWarehouseFeeAccountService.deleteWWarehouseFeeAccountByWarehouseFeeAccountNumber(warehouseFeeAccount.getWarehouseFeeAccountNumber());
        //插入账单
        rtn = wWarehouseFeeAccountService.insertWWarehouseFeeAccount(warehouseFeeAccount);
        //更新出库信息
        //rtn = wExitWarehouseInfoService.updateWExitWarehouseInfo(wExitWarehouseInfo);

        return rtn;
    }

    /**
     *处理仓储费账单，煤矿
     */
    private Integer handleMineWarehouseFeeAccount(WExitWarehouseInfo wExitWarehouseInfo)
    {
        Integer rtn = 0;

//        List<TGoodsInfo> list = tGoodsInfoService.selectTGoodsInfoByNumber(3, wExitWarehouseInfo.getExitWarehouseNumber());

        String goodsType = wExitWarehouseInfo.getGoodsType();
        Double indoorWarehousePrice = 0.0;
        Double outdoorWarehousePrice = 0.0;
        Double warehouseWeight = 0.0;
        Double warehouseFee = 0.0;
//        Double goodsWarehouseFee = 0.0;
//        Double goodsWeight = 0.0;

        WWarehouseFeeAccount warehouseFeeAccount = new WWarehouseFeeAccount();
        warehouseFeeAccount.setWarehouseFeeAccountNumber(wExitWarehouseInfo.getExitWarehouseNumber().replace("EX","WA"));
        //仓储费列表
        List<WWarehouseFeeRule> warehouseFeelist = wWarehouseFeeRuleService.selectWWarehouseFeeRuleListByCustomerName(wExitWarehouseInfo.getExitWarehouseCustomer());
//        logger.debug("WWW " + "warehouseFeelist = " + warehouseFeelist);
        if(warehouseFeelist.size() > 0) {
            for (WWarehouseFeeRule item : warehouseFeelist) {
                if (item.getRuleType().equals(RuleType.COMMON.getInfo()) & item.getGoodsType().equals(goodsType)) {
                    indoorWarehousePrice = item.getIndoorWarehousePrice();
                    outdoorWarehousePrice = item.getOutdoorWarehousePrice();
                }
                if (item.getRuleType().equals(RuleType.CUSTOMIZED.getInfo()) & item.getGoodsType().equals(goodsType)) {
                    indoorWarehousePrice = item.getIndoorWarehousePrice();
                    outdoorWarehousePrice = item.getOutdoorWarehousePrice();
                }
            }

            warehouseWeight = wExitWarehouseInfo.getWeight();
            if ((!(wExitWarehouseInfo.getWarehouseType() == null || wExitWarehouseInfo.getWarehouseType().isEmpty())) && wExitWarehouseInfo.getWarehouseType().equals("室外库")) {
                warehouseFee = outdoorWarehousePrice * warehouseWeight;
            } else {
                warehouseFee = indoorWarehousePrice * warehouseWeight;
            }
            warehouseFeeAccount.setIndoorWarehousePrice(indoorWarehousePrice);
            warehouseFeeAccount.setOutdoorWarehousePrice(outdoorWarehousePrice);
            warehouseFee = Math.round(warehouseFee * 100.0) / 100.0;
            warehouseFeeAccount.setStorageFee(warehouseFee);
        } else {
            logger.error("No Warehouse Fee Rule ...");
        }


        Integer freeStorageDays = 0;
        String overduePriceMode = "";
        Double overduePrice = 0.0;
        Double overdueGoodsFee = 0.0;
        Double overdueWarehouseFee = 0.0;
        Integer betweenDays = 0;
        Integer storageDays = 0;

        // 超期费列表
        List<WOverdueFeeRule> overdueFeelist = wOverdueFeeRuleService.selectWOverdueFeeRuleListByCustomerName(wExitWarehouseInfo.getExitWarehouseCustomer());
//        logger.debug("WWW " + "overdueFeelist = " + overdueFeelist);
        if(overdueFeelist.size() > 0) {
            for (WOverdueFeeRule item : overdueFeelist) {
                if (item.getRuleType().equals(RuleType.COMMON.getInfo()) & item.getGoodsType().equals(goodsType)) {
                    freeStorageDays = item.getFreeStorage();
                    overduePriceMode = item.getOverduePriceMode();
                    overduePrice = item.getOverduePrice();
                }
                if (item.getRuleType().equals(RuleType.CUSTOMIZED.getInfo()) & item.getGoodsType().equals(goodsType)) {
                    freeStorageDays = item.getFreeStorage();
                    overduePriceMode = item.getOverduePriceMode();
                    overduePrice = item.getOverduePrice();
                }
            }
            //货物扩展辅助，出库重量，入手
            List<WGoodsExtAssist> goodsExtAssists = wGoodsExtAssistService.selectWGoodsExtAssistListByExitWarehouseNumber(wExitWarehouseInfo.getExitWarehouseNumber(), "已出库");
            for(WGoodsExtAssist goodsExtAssist : goodsExtAssists)
            {
                goodsExtAssist.getExitWarehouseWeight();
                if( (goodsExtAssist.getExitWarehouseTime() == null) || (goodsExtAssist.getEnterWarehouseTime() == null)) {
                    betweenDays = 0;
                    logger.error("ExitWarehouseTime or EnterWarehouseTime is null, betweenDays = 0");
                } else {
                    betweenDays = Math.toIntExact((goodsExtAssist.getExitWarehouseTime().getTime() - goodsExtAssist.getEnterWarehouseTime().getTime())/(24 * 60 * 60 *1000));
                }
                logger.debug("WWW " + "betweenDays  = " + betweenDays);
                logger.debug("WWW " + "freeStorageDays  = " + freeStorageDays);

                if (overduePriceMode.equals("吨x天")) {
                    if (betweenDays > freeStorageDays) {
                        overdueGoodsFee = overduePrice * (betweenDays - freeStorageDays) * goodsExtAssist.getExitWarehouseWeight();
                        overdueGoodsFee = Math.round(overdueGoodsFee * 100.0) / 100.0;
//                        item.setOverdueFee(overdueGoodsFee);
                        overdueWarehouseFee = overdueWarehouseFee + overdueGoodsFee;
                    } else {
//                        item.setOverdueFee(0.0);
                    }
                } else if (overduePriceMode.equals("吨x月")) {
                    // 每月按30天计算
                    if ((betweenDays - freeStorageDays) < 30) {
//                        item.setOverdueFee(0.0);
                    } else {
                        overdueGoodsFee = overduePrice * (betweenDays - freeStorageDays) * goodsExtAssist.getExitWarehouseWeight() / 30.0;
                        overdueGoodsFee = Math.round(overdueGoodsFee * 100.0) / 100.0;
//                        item.setOverdueFee(overdueGoodsFee);
                        overdueWarehouseFee = overdueWarehouseFee + overdueGoodsFee;
                    }
                }
            }

            //超期费，免堆天数
            warehouseFeeAccount.setFreeStorage(freeStorageDays);
            //超期费，计算模式
            warehouseFeeAccount.setOverduePriceMode(overduePriceMode);
            //超期费，单价
            warehouseFeeAccount.setOverduePrice(overduePrice);
            //超期费，库存天数
            warehouseFeeAccount.setStorageDay(betweenDays);
            //超期费，总数
            warehouseFeeAccount.setOverdueFee(overdueGoodsFee);
            //账单，结算模式
            warehouseFeeAccount.setWarehouseSettlementMode(wExitWarehouseInfo.getSettlementMode());
            warehouseFeeAccount.setCreateBy(getNickName());
            warehouseFeeAccount.setCreateTime(DateUtils.getNowDate());
            //仓储费合计
            warehouseFeeAccount.setWarehouseFeeTotal(Math.round(((warehouseFee + overdueWarehouseFee) * 100.0)) / 100.0);

            warehouseFeeAccount.setWarehouseSettlementCustomer(wExitWarehouseInfo.getExitWarehouseCustomer());
            warehouseFeeAccount.setWarehouseSettlementMode(wExitWarehouseInfo.getSettlementMode());
            warehouseFeeAccount.setWarehouseSettlementMode(wExitWarehouseInfo.getSettlementMode());
        } else {
            logger.error("No Overdue Fee Rule ...");
        }
        //删除账单
        rtn = wWarehouseFeeAccountService.deleteWWarehouseFeeAccountByWarehouseFeeAccountNumber(warehouseFeeAccount.getWarehouseFeeAccountNumber());
        //插入账单
        rtn = wWarehouseFeeAccountService.insertWWarehouseFeeAccount(warehouseFeeAccount);
        //更新出库信息
        //rtn = wExitWarehouseInfoService.updateWExitWarehouseInfo(wExitWarehouseInfo);

        return rtn;
    }


    /**
     * 获取货物重量合计
     */
    @GetMapping(value = "/exitweightsum")
    public AjaxResult exitweightsum(WExitWarehouseInfo wExitWarehouseInfo)
    {
        List<TGoodsWeightSum> list = wExitWarehouseInfoService.getWeightSumByExitWarehouseInfo(wExitWarehouseInfo);
//        logger.debug("GGG " + "getWeightSumByExitWarehouseInfo = " + list);
        return success(list);
    }

    /**
     * 更新“车牌号”相关信息
     */
    private void updateMobileAndNumberRelateInfo(WExitWarehouseInfo wExitWarehouseInfo) {
        TVehicleDriverInfo tVehicleDriverInfo = new TVehicleDriverInfo();
        //更新车牌，司机，电话
        if(!(wExitWarehouseInfo.getExitWarehouseVehicle() == null || wExitWarehouseInfo.getExitWarehouseVehicle().isEmpty())) {
//            logger.debug("HHH " + "edit = " + tVehicleDriverInfo);
            tVehicleDriverInfo.setVehicleLicenseNumber(wExitWarehouseInfo.getExitWarehouseVehicle());
            List<TVehicleDriverInfo> list = tVehicleDriverInfoService.selectTVehicleDriverInfoByNumber(tVehicleDriverInfo);
            tVehicleDriverInfo.setDriverName(wExitWarehouseInfo.getExitWarehouseDriver());
            tVehicleDriverInfo.setContactMobile(wExitWarehouseInfo.getExitWarehouseMobile());
            if (list.isEmpty()) {
                if((tVehicleDriverInfo.getDriverName() == null || tVehicleDriverInfo.getDriverName().isEmpty())
                        && (tVehicleDriverInfo.getContactMobile() == null || tVehicleDriverInfo.getContactMobile().isEmpty())) {return;}
                tVehicleDriverInfo.setCreateBy(getNickName());
                tVehicleDriverInfo.setUpdateBy(null);
                tVehicleDriverInfoService.insertTVehicleDriverInfo(tVehicleDriverInfo);
            } else {
                tVehicleDriverInfo.setVehicleDriverId(list.get(0).getVehicleDriverId());
                tVehicleDriverInfo.setUpdateBy(getNickName());
                tVehicleDriverInfoService.updateTVehicleDriverInfo(tVehicleDriverInfo);
            }
        } else {
            logger.debug("Vehicle HHH Number is empty ");
        }
//
    }

    /**
     * 处理矿物（煤炭，矿粉），货物信息
     * @param operate，
     * @param wExitWarehouseInfo
     */
    private Integer handleMineTGoodsInfo(BusinessType operate, WExitWarehouseInfo wExitWarehouseInfo)
    {
        Integer numberOfPiece = 0;
        if (!wExitWarehouseInfo.getGoodsType().equals("煤炭"))
        {
            return 0;
        }
        /**
         * 插入货物
         */
        if(BusinessType.INSERT == operate)
        {
            numberOfPiece = insertMineTGoodsInfo(wExitWarehouseInfo);
        }

        /**
         * 修改货物，先删除货物，后插入货物
         */
        if(BusinessType.UPDATE == operate)
        {
            /**
             * 删除货物，物理删除
             */
            tGoodsInfoService.deleteTGoodsInfoByNumberExt(1 /*出库单号*/, wExitWarehouseInfo.getExitWarehouseNumber());
            /**
             * 插入货物
             */
            numberOfPiece = insertMineTGoodsInfo(wExitWarehouseInfo);
        }

        /**
         * 修改货物，先删除货物，后插入货物
         */
        if(BusinessType.DELETE == operate)
        {
            /**
             * 删除货物，物理删除
             */
//            tGoodsInfoService.deleteTGoodsInfoByExitWarehouseNumberExt(wExitWarehouseInfo.getExitWarehouseNumber());
        }
        return numberOfPiece;
    }

    /**
     * 插入货物信息
     * @param wExitWarehouseInfo
     */
    private Integer insertMineTGoodsInfo(WExitWarehouseInfo wExitWarehouseInfo)
    {
        Integer numberOfPiece = 0;
        /**
         * 重量为0.0，直接返回，不插入货物
         */
        if(wExitWarehouseInfo.getWeight().compareTo(0.0) == 0) {
            return 0;
        }
        /**
         * 拆分入库货物，毛重大于55.0吨
         */
        TGoodsInfo tGoodsInfo = new TGoodsInfo();

        tGoodsInfo.setBundleNumber(OrderUtils.getOrderNumber("CL", "-"));
        tGoodsInfo.setGoodsType(wExitWarehouseInfo.getGoodsType());
        tGoodsInfo.setProduct(wExitWarehouseInfo.getProduct());
        tGoodsInfo.setSpecification(wExitWarehouseInfo.getSpecification());
        tGoodsInfo.setSteelGrade(wExitWarehouseInfo.getSteelGrade());
        tGoodsInfo.setWeight(wExitWarehouseInfo.getWeight());
        tGoodsInfo.setGrossWeight(wExitWarehouseInfo.getGrossWeight());
        tGoodsInfo.setTareWeight(wExitWarehouseInfo.getTareWeight());
        tGoodsInfo.setNetWeight(wExitWarehouseInfo.getNetWeight());
        tGoodsInfo.setDeductWeight(wExitWarehouseInfo.getDeductWeight());
        tGoodsInfo.setRecordSource(wExitWarehouseInfo.getRecordSource());
        tGoodsInfo.setInventoryStatus("入库中");
        tGoodsInfo.setWarehouseType(wExitWarehouseInfo.getWarehouseType());
        tGoodsInfo.setLogisticsParkName(wExitWarehouseInfo.getLogisticsParkName());
        tGoodsInfo.setWarehouseLocateName(wExitWarehouseInfo.getWarehouseLocateName());
        tGoodsInfo.setRegionLocateName(wExitWarehouseInfo.getRegionLocateName());
        tGoodsInfo.setGoodsLocateName(wExitWarehouseInfo.getGoodsLocateName());
        tGoodsInfo.setWarehouseTotalLocate(wExitWarehouseInfo.getWarehouseTotalLocate());

        tGoodsInfo.setExitWarehouseNumber(wExitWarehouseInfo.getExitWarehouseNumber());
        tGoodsInfo.setExitWarehouseCustomer(wExitWarehouseInfo.getExitWarehouseCustomer());
        tGoodsInfo.setExitWarehouseDriver(wExitWarehouseInfo.getExitWarehouseDriver());
        tGoodsInfo.setExitWarehouseVehicle(wExitWarehouseInfo.getExitWarehouseVehicle());
        tGoodsInfo.setExitWarehousePerson(wExitWarehouseInfo.getCreateBy());
        tGoodsInfo.setExitWarehouseTime(wExitWarehouseInfo.getExitWarehouseTime());
        tGoodsInfo.setGoodsRightCustomer(wExitWarehouseInfo.getExitWarehouseCustomer());

        tGoodsInfo.setCreateBy(getNickName());
        //logger.debug("QQQ " + "wExitWarehouseInfo = " + wExitWarehouseInfo);
        if (StringUtils.isNotNull(wExitWarehouseInfo.getGrossWeight()) && (wExitWarehouseInfo.getGrossWeight() > 55.0)) {
            double weight = wExitWarehouseInfo.getWeight();
            double grossWeight = wExitWarehouseInfo.getGrossWeight();
            double tareWeight = wExitWarehouseInfo.getTareWeight();
            double netWeight = wExitWarehouseInfo.getNetWeight();
            double deductWeight = wExitWarehouseInfo.getDeductWeight();
            weight = Math.round(weight / 2.0 * 1000.0) / 1000.0;
            grossWeight = Math.round((grossWeight + tareWeight) / 2.0 * 1000.0) / 1000.0;
            netWeight = Math.round(netWeight / 2.0 * 1000.0) / 1000.0;
            deductWeight = Math.round(deductWeight / 2.0 * 1000.0) / 1000.0;

            tGoodsInfo.setWeight(weight);
            tGoodsInfo.setGrossWeight(grossWeight);
//            tGoodsInfo.setTareWeight(tareWeight);
            tGoodsInfo.setNetWeight(netWeight);
            tGoodsInfo.setDeductWeight(deductWeight);
            tGoodsInfoService.insertTGoodsInfo(tGoodsInfo);

            tGoodsInfo.setGrossWeight(Math.round((wExitWarehouseInfo.getGrossWeight() - grossWeight + tareWeight) * 1000.0) / 1000.0);
//            tGoodsInfo.setTareWeight(tareWeight);
            tGoodsInfo.setNetWeight(Math.round((wExitWarehouseInfo.getNetWeight() - netWeight) * 1000.0) / 1000.0);
            tGoodsInfo.setDeductWeight(Math.round((wExitWarehouseInfo.getDeductWeight() - deductWeight) * 1000.0) / 1000.0);
//            tGoodsInfo.setBundleNumber(OrderUtils.getOrderNumber(vehicle, "-"));
            tGoodsInfo.setBundleNumber(OrderUtils.getOrderNumber("CL", "-"));
            tGoodsInfoService.insertTGoodsInfo(tGoodsInfo);

            numberOfPiece = 2;
        } else {
            tGoodsInfoService.insertTGoodsInfo(tGoodsInfo);
        }
        return numberOfPiece;
    }

    /**
     * 处理煤炭库存
     * @param operate
     * @param wExitWarehouseInfo
     */
    private void handleMineInventory(BusinessType operate, WExitWarehouseInfo wExitWarehouseInfo)
    {
        WGoodsExt wGoodsExt = new WGoodsExt();
        wGoodsExt.setGoodsType(wExitWarehouseInfo.getGoodsType());
        wGoodsExt.setProduct(wExitWarehouseInfo.getProduct());
        wGoodsExt.setSpecification(wExitWarehouseInfo.getSpecification());
        wGoodsExt.setSteelGrade(wExitWarehouseInfo.getSteelGrade());

        wGoodsExt.setLogisticsParkName(wExitWarehouseInfo.getLogisticsParkName());
        wGoodsExt.setWarehouseLocateName(wExitWarehouseInfo.getWarehouseLocateName());
        wGoodsExt.setRegionLocateName(wExitWarehouseInfo.getRegionLocateName());
        //wGoodsExt.setGoodsLocateName(wEnterWarehouseInfo.getGoodsLocateName());
        //wGoodsExt.setLayerLocateName(wEnterWarehouseInfo.setLayerLocateName());

        wGoodsExt.setGoodsRightCustomer(wExitWarehouseInfo.getExitWarehouseCustomer());

        Integer record = wGoodsExtService.selectWGoodsExtRecordCountByGoodsExt(wGoodsExt);
        //logger.debug("GGG " + "handleMineInventory record = " + record);
        /**
         * 确认入库
         */
        if(BusinessType.CONFIRM == operate) {
            //logger.debug("GGG " + "handleMineInventory wExitWarehouseInfo = " + wExitWarehouseInfo);
            if(record > 0) {
                /**
                 * 扣减库存
                 */
                WGoodsExt goodsExt = wGoodsExtService.selectWGoodsExtOneByGoodsExt(wGoodsExt);
                double weight = goodsExt.getWeight();
                weight = weight - wExitWarehouseInfo.getWeight();
                weight = Math.round(weight * 1000.0) / 1000.0;
                goodsExt.setWeight(weight);
                wGoodsExtService.updateWGoodsExt(goodsExt);
                /**
                 * 辅助，切库存
                 */
                double exitRemaindWeight = wExitWarehouseInfo.getWeight();
                //logger.debug("GGG " + "handleMineInventory wExitWarehouseInfo = " + wExitWarehouseInfo);
                //先取一次入库，看重量
                WGoodsExtAssist goodsExtAssist = new WGoodsExtAssist();
                do {
                    goodsExtAssist = wGoodsExtAssistService.selectWGoodsExtAssistOneByEnterWarehouseTimeAsc(goodsExt.getBundleNumber(), "已在库");
                    if(StringUtils.isNotNull(goodsExtAssist))
                    {
                        double tempRemaindWeight = exitRemaindWeight;
                        double remaindWarehouseWeight =  goodsExtAssist.getRemaindWarehouseWeight();
                        exitRemaindWeight = exitRemaindWeight - remaindWarehouseWeight;
                        logger.debug("XXX " + "handleMineInventory exitRemaindWeight = " + exitRemaindWeight);
                        //logger.debug("GGG " + "handleMineInventory goodsExtAssist = " + goodsExtAssist);
                        if(exitRemaindWeight < 0.0)
                        {
//                            logger.debug("GGG " + "handleMineInventory exitRemaindWeight = " + exitRemaindWeight);
//                            logger.debug("GGG " + "handleMineInventory exitRemaindWeight = " + goodsExtAssist.getGoodsExtAssistId());
                            goodsExtAssist.setExitWarehouseMark("拆分出库");
                            goodsExtAssist.setInventoryStatus("已出库");
                            goodsExtAssist.setRemaindWarehouseWeight(0.0);
                            goodsExtAssist.setExitWarehouseNumber(wExitWarehouseInfo.getExitWarehouseNumber());
                            goodsExtAssist.setExitWarehouseTime(wExitWarehouseInfo.getExitWarehouseTime());
                            goodsExtAssist.setExitWarehouseWeight(tempRemaindWeight);
                            wGoodsExtAssistService.updateWGoodsExtAssistExitWarehouseRelFields(goodsExtAssist);
                            //二分拆解，未出库
                            double enterWeight = (Math.round((0.0 - exitRemaindWeight) * 1000.0) / 1000.0);
                            goodsExtAssist.setInventoryStatus("已在库");
                            goodsExtAssist.setParentId(goodsExtAssist.getGoodsExtAssistId());
                            goodsExtAssist.setGoodsExtAssistId(null);
                            goodsExtAssist.setLevelMark("1");
                            goodsExtAssist.setExitWarehouseMark("拆分入库");
                            goodsExtAssist.setWeight(enterWeight);
                            goodsExtAssist.setGrossWeight(0.0);
                            goodsExtAssist.setTareWeight(0.0);
                            goodsExtAssist.setNetWeight(0.0);
                            goodsExtAssist.setDeductWeight(0.0);
                            goodsExtAssist.setEnterWarehouseWeight(enterWeight);
                            goodsExtAssist.setRemaindWarehouseWeight(enterWeight);
                            goodsExtAssist.setExitWarehouseNumber(null);
                            goodsExtAssist.setExitWarehouseTime(null);
                            goodsExtAssist.setExitWarehouseWeight(0.0);
                            goodsExtAssist.setUpdateBy("");
                            goodsExtAssist.setUpdateTime(null);

                            wGoodsExtAssistService.insertWGoodsExtAssist(goodsExtAssist);
                            break;
                        } else {
//                            logger.debug("GGG else " + "handleMineInventory exitRemaindWeight = " + exitRemaindWeight);
//                            logger.debug("GGG " + "handleMineInventory exitRemaindWeight = " + goodsExtAssist.getGoodsExtAssistId());
                            goodsExtAssist.setExitWarehouseMark("运输出库");
                            goodsExtAssist.setInventoryStatus("已出库");
                            goodsExtAssist.setRemaindWarehouseWeight(0.0);
                            goodsExtAssist.setExitWarehouseNumber(wExitWarehouseInfo.getExitWarehouseNumber());
                            goodsExtAssist.setExitWarehouseTime(wExitWarehouseInfo.getExitWarehouseTime());
                            goodsExtAssist.setExitWarehouseWeight(remaindWarehouseWeight);
                            wGoodsExtAssistService.updateWGoodsExtAssistExitWarehouseRelFields(goodsExtAssist);
                        }
                    } else {
                        logger.error("WExitWarehouseInfoController, Confirm exit warehouse, Operate Assist Inventory Failure !");
                        break;
                    }
                } while(exitRemaindWeight > 0.0);

            } else {
                logger.error("WExitWarehouseInfoController, Confirm exit warehouse, Subtract Inventory Failure !");
            }
        }

        /**
         * 撤销入库
         */
        if(BusinessType.REVOKE == operate)
        {
            /**
             * 还原库存
             */
            if(record > 0) {
                WGoodsExt goodsExt = wGoodsExtService.selectWGoodsExtOneByGoodsExt(wGoodsExt);
                double weight = goodsExt.getWeight();
                weight = weight + wExitWarehouseInfo.getWeight();
                weight = Math.round(weight * 1000.0) / 1000.0;
                goodsExt.setWeight(weight);
                wGoodsExtService.updateWGoodsExt(goodsExt);
                //二分还原
                List<WGoodsExtAssist> goodsExtAssists = wGoodsExtAssistService.selectWGoodsExtAssistListByExitWarehouseNumber(wExitWarehouseInfo.getExitWarehouseNumber(), "已出库");
                for(WGoodsExtAssist goodsExtAssist : goodsExtAssists)
                {
                    goodsExtAssist.setExitWarehouseMark("撤销入库");
                    goodsExtAssist.setInventoryStatus("已在库");
                    //double remaindWarehouseWeight = goodsExtAssist.getEnterWarehouseWeight() - goodsExtAssist.getRemaindWarehouseWeight();
                    //logger.debug("YYY " + "handleMineInventory exitRemaindWeight = " + remaindWarehouseWeight);
                    goodsExtAssist.setRemaindWarehouseWeight(goodsExtAssist.getExitWarehouseWeight());
                    goodsExtAssist.setExitWarehouseNumber(null);
                    goodsExtAssist.setExitWarehouseTime(null);
                    goodsExtAssist.setExitWarehouseWeight(0.0);
                    wGoodsExtAssistService.updateWGoodsExtAssistExitWarehouseRelFields(goodsExtAssist);
                }

            } else {
                logger.error("WExitWarehouseInfoController, Revoke exit warehouse, Increase Inventory Failure !");
            }
        }
    }

}
